const FUN = require('../comm/func');
const PMR = require('../utils/policyManger');
const timLib = require('../comm/time-lib');
const mbLib = require('../comm/modbus-lib');

module.exports = class jsonVar
{
  // 将数据库选项缓存到redis
  // policy 数据库policy信息
  // opts 数据库json信息
  // CacheCallback 执行存储的子函数
  static InitCache(policy, opts, CacheFunc)
  {
    let devConf = PMR.baseParam(policy);//即将缓存到redis的参数

    if ( 0 ) {
      console.error('wrong json-to-mb policy',policy.id);
      return false;
    }

    //json options参数
    devConf.channel = opts.channel; // 通道号
    devConf.addr = opts.addr; // 从站地址
    devConf.reg_start = opts.reg_start; // 寄存器起始
    devConf.vars = opts.vars; // 变量列表
    devConf.data_width = opts.data_width; // 字节宽度
    devConf.calc = opts.calc; // 算式
    devConf.hwid = policy.master;

    CacheFunc(policy.id, policy.master, devConf); // 记录到缓存
  } // end InitCache

  // 处理json数据
  // topic = {project,devType,func,devId}
  // dConf即InitCache中的obj
  // dataBuf即mq消息内容，buf对象
  static async DataIn(topic, dConf, DataBuf)
  {
    if (topic.func != 'var') return; // topic过滤
    let devId = topic.devId.split('-');
    if (devId[0] != dConf.channel) return; // 有值，则通道过滤
    let channel= parseInt(dConf.channel);

    let varAllow = dConf.vars.split(','); // 允许记录的变量名

    // 先发出rx包
    let sendRxArr = [];
    sendRxArr.push(dConf.addr & 0xff);
    sendRxArr.push(0x03);
    sendRxArr.push((parseInt(dConf.reg_start) >> 8) & 0xff);
    sendRxArr.push(parseInt(dConf.reg_start) & 0xff);
    sendRxArr.push((varAllow.length >> 8) & 0xff);
    sendRxArr.push(varAllow.length & 0xff);
    let crc = mbLib.crc16(sendRxArr);
    sendRxArr.push(crc >> 8);
    sendRxArr.push(crc & 0xff);

    let rxTopic = `${topic.project}/${topic.devType}/tx/${devId[1]}`;
    PMR.mqPub(rxTopic, Buffer.from(sendRxArr)); // 发包
    pcyLog('Rx:', rxTopic, Buffer.from(sendRxArr));

    // 解析json报文
    let jsonStr = DataBuf.toString().replace(/\x00/g, '');
    let varsObj = {};
    try {
      varsObj = JSON.parse(jsonStr); // 收到的变量值
    } catch(err) {
      pcyLog('JSON parse error:', jsonStr);
      return;
    }

    // 填充缺省算式
    let calc = dConf.calc.split(','); // 变量表达式
    if (calc.length == 0) calc[0] = '#v';
    for (let i in varAllow) {
      if (typeof calc[i] == 'undefined' || calc[i].length == 0) calc[i] = calc[i-1];
    }

    // 填写
    let dataFmt = dConf.data_width;
    let txArr = [];
    txArr.push(dConf.addr & 0xff);
    txArr.push(0x03);
    txArr.push((varAllow.length * dataFmt.split(':')[0]) & 0xff);
    for (let varName of varAllow) {
      let value = 0;
      if (typeof varsObj[varName] != 'undefined') value = varsObj[varName];

      switch (dataFmt) {
        case '2:n':
          txArr.push((value >> 8) & 0xff);
          txArr.push(value & 0xff);
          break;
        case '4:n':
          txArr.push((value >> 24) & 0xff);
          txArr.push((value >> 16) & 0xff);
          txArr.push((value >> 8) & 0xff);
          txArr.push(value & 0xff);
          break;
        case '4:f':
          let data = FUN.ieee745_floatSave(value);
          txArr.push((data >> 24) & 0xff);
          txArr.push((data >> 16) & 0xff);
          txArr.push((data >> 8) & 0xff);
          txArr.push(data & 0xff);
          break;
      }
    }

    let dataCrc = mbLib.crc16(txArr);
    txArr.push(dataCrc >> 8);
    txArr.push(dataCrc & 0xff);

    let txTopic = `${topic.project}/${topic.devType}/rx/${devId[1]}`;
    PMR.mqPub(txTopic, Buffer.from(txArr)); // 发包
    pcyLog('Tx:', txTopic, Buffer.from(txArr));
  }

  // 通过算式计算变量值
  static VarValueCalc(dConf, value, calc)
  {
    let stamp = timLib.NowStamp();

    //进行算式计算
    if (calc) {
      calc = calc.replace(/#v/g, value);
      calc = calc.replace(/#t/g, parseInt(stamp/1000));
      try {
        value = eval(calc);
        return Number(value);
      } catch(err) {
        pcyLog('eval var calc string error! policy', dConf.policy_id);
        return -1;
      }
    }
  }




} //end class Modbus